package core.lib;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.Vector;

import core.lib.interfaces.HttpAgent;
import core.lib.interfaces.LogAgent;
import core.lib.interfaces.SocketAgent;
import core.lib.model.CoreRequest;
import core.lib.model.Module;
import core.lib.network.NetworkConstants;
import core.lib.network.NetworkModule;
import core.lib.tools.CoreLog;

/**
 * LibAgent是底层库的总入口。
 * 
 * 为了能够在多任务场景中使用，可以同时构造多个FetionCore实例，每个实例拥有完全独立的运行环境。
 * 
 * 结束使用时务必调用destroy()方法，使得底层库会终止各个模块运行并释放资源。
 * 
 * @author luolong
 * 
 */
public class CoreLib
{
	// 用于存放活动的Module
	private Vector<Module> mActiveModules;

	private final CoreEventDispatcher mCoreEventDispatcher;
	private final CoreRequestDispatcher mCoreRequestDispatcher;

//	private final LogicModule mLogicModule;

	/**
	 * 为了提供任务，不再封装单例，客户端可以根据需要自行创建多个实例，但是同一个用户必须在一个实例中运行。 请客户端自行管理好FetionCore的实例。中止请调用destroy()方法。
	 */
	public CoreLib()
	{
		// 初始化基本的组件，这个必须放在最前面
		mActiveModules = new Vector<Module>(3);

		mCoreEventDispatcher = new CoreEventDispatcher();
		mCoreRequestDispatcher = new CoreRequestDispatcher();

		// 可动态拆装的模块，各模块应该没有强依赖关系

//		mLogicModule = new LogicModule(mCoreRequestDispatcher, mCoreEventDispatcher);

//		mActiveModules.add(new DataModule(mCoreRequestDispatcher, mCoreEventDispatcher));
		mActiveModules.add(new NetworkModule(mCoreRequestDispatcher, mCoreEventDispatcher));
//		mActiveModules.add(mLogicModule);

		startModules();
	}

	/**
	 * 启动各模块。
	 */
	private void startModules()
	{
		synchronized (mActiveModules)
		{
			for (Module module : mActiveModules)
			{
				module.start();
			}
		}
	}

	public void sendCoreRequest(CoreRequest req)
	{
		if (req != null)
		{
			mCoreRequestDispatcher.sendCoreRequest(req);
		}
	}

	/**
	 * 获取CoreEventDispatcher实例，用于注册和触发飞信事件。
	 * 
	 * @return CoreEventDispatcher实例
	 */
	public CoreEventDispatcher getCoreEventDispatcher()
	{
		return mCoreEventDispatcher;
	}

	/**
	 * 获取CoreRequestDispatcher实例，用于注册和发送Request请求。
	 * 
	 * @return CoreRequestDispatcher实例
	 */
	public CoreRequestDispatcher getCoreRequestDispatcher()
	{
		return mCoreRequestDispatcher;
	}

	/**
	 * 设置日志能力实现对象。客户端提供日志能力实现。
	 * 
	 * @param logAgent
	 *            日志能力实现对象
	 */
	public void setLoggerClass(Class<LogAgent> logAgent)
	{
		CoreLog.setLogAgent(logAgent);
	}

	/**
	 * 设置Socket能力实现对象。客户端提供Socket能力实现。
	 * 
	 * @param socketAgent
	 *            Socket能力实现对象
	 */
	public void setSocketAgentClass(Class<SocketAgent> socketAgent)
	{
		URI targetURI = null;
		try
		{
			targetURI = new URI("weaver://network/setSocketAgentClass");
		}
		catch (URISyntaxException e)
		{
			
			CoreLog.log(CoreLog.LEVEL_ERROR, CoreConstants.CORE_TAG, null, e);
		}
		CoreRequest req = new CoreRequest(targetURI, null);
		req.addParameter(NetworkConstants.Parameters.AGENT_CLASS, socketAgent);
		sendCoreRequest(req);
	}

	/**
	 * 设置Http能力实现对象。客户端提供Http能力实现。
	 * 
	 * @param httpAgent
	 *            Http能力实现对象
	 */
	public void setHttpAgent(HttpAgent httpAgent)
	{
		URI targetURI = null;
		try
		{
			targetURI = new URI("weaver://network/setHttpAgentClass");
		}
		catch (URISyntaxException e)
		{
			CoreLog.log(CoreLog.LEVEL_ERROR, CoreConstants.CORE_TAG, null, e);
		}
		CoreRequest req = new CoreRequest(targetURI, null);
		req.addParameter(NetworkConstants.Parameters.AGENT_CLASS, httpAgent);
		mCoreRequestDispatcher.sendCoreRequest(req);
	}

	/**
	 * 设置数据持久化能力实现对象。客户端提供数据持久化能力实现。
	 * 
	 * @param dataAgent
	 *            数据持久化能力实现对象
	 */
//	public void setDataStorageAgent(DataBaseAgent dataAgent)
//	{
//		URI targetURI = null;
//		try
//		{
//			targetURI = new URI("fetion://data/setDataStoreAgent");
//		}
//		catch (URISyntaxException e)
//		{
//			CoreLog.log(getClass().getName(), null, e);
//		}
//		CoreRequest req = new CoreRequest(targetURI, null);
//		req.addParameter(CoreRequestConstants.PARAM_DATA_AGENT, dataAgent);
//		mCoreRequestDispatcher.sendCoreRequest(req);
//	}

	public void destroy()
	{
		synchronized (mActiveModules)
		{
			for (Module module : mActiveModules)
			{
				module.interrupt();
			}
		}
	}
}
